package no.ntnu.fp.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import no.ntnu.fp.gui.EventDispatcher;
import no.ntnu.fp.model.events.AppointmentsChangedEvent;
import no.ntnu.fp.model.events.AppointmentsClearedEvent;
import no.ntnu.fp.model.events.MeetingsChangedEvent;
import no.ntnu.fp.model.events.MeetingsClearedEvent;

public class CalendarModel {
	private ConcurrentHashMap<Employee, List<Appointment>> appointments;
	private ConcurrentHashMap<Employee, List<Meeting>> meetings;

	public CalendarModel() {
		appointments = new ConcurrentHashMap<Employee, List<Appointment>>();
		meetings = new ConcurrentHashMap<Employee, List<Meeting>>();
	}
	//change with putifabsent?
			public synchronized void setAppointmentsForEmployee(Employee emp, List<Appointment> appointments) {
				List<Appointment> previousList = this.appointments.get(emp);
				AppointmentsChangedEvent evt = null;
				if (previousList == null) {
					this.appointments.put(emp, appointments);
					evt = new AppointmentsChangedEvent(this, emp, Collections.<Appointment>emptyList(), appointments);
				} else {
					evt = new AppointmentsChangedEvent(this, emp, previousList, appointments);
					previousList.clear();
					previousList.addAll(appointments);
				}

				EventDispatcher.dispatchEvent(evt);
			}

			public synchronized void removeEmployeeCalendar(Employee employee){
				List<Appointment> previuosAppointments = this.appointments.get(employee);
				List<Meeting> prevoiusMeetings = this.meetings.get(employee);
				this.meetings.remove(employee);
				this.appointments.remove(employee);
				EventDispatcher.dispatchEvent(new AppointmentsChangedEvent
						(this, employee, previuosAppointments, Collections.<Appointment>emptyList()));
				EventDispatcher.dispatchEvent(
						new MeetingsChangedEvent(this, employee, prevoiusMeetings, 
								Collections.<Meeting>emptyList()));
			}

			public synchronized void setMeetingsForEmployee(Employee emp, List<Meeting> meetings) {
				List<Meeting> previousList = this.meetings.get(emp);
				MeetingsChangedEvent evt = null;
				if (previousList == null) {
					this.meetings.put(emp, meetings);
					evt = new MeetingsChangedEvent(this, emp, Collections.<Meeting>emptyList(), meetings);
				} else {
					evt = new MeetingsChangedEvent(this, emp, previousList, meetings);
					previousList.clear();
					previousList.addAll(meetings);
				}

				EventDispatcher.dispatchEvent(evt);
			}

			public synchronized void addOrUpdateMeeting(Employee emp, Meeting meet){
				List<Meeting> list = this.meetings.get(emp);
				if (list == null) {
					list = new ArrayList<Meeting>();
				}
				List<Meeting> old = new ArrayList<Meeting>(list);
				list.remove(meet); //synchronized (this) instead of entire method sync?
						list.add(meet);
				MeetingsChangedEvent evt = 
					new MeetingsChangedEvent(this, emp, old, list);
				EventDispatcher.dispatchEvent(evt);          
			}
			public synchronized void addOrUpdateAppointment(Employee emp, Appointment app){
				List<Appointment> list = this.appointments.get(emp);
				List<Appointment> old = new ArrayList<Appointment>(list);
				list.remove(app); 
				list.add(app);
				AppointmentsChangedEvent evt 
				= new AppointmentsChangedEvent(this, emp, old, list);
				EventDispatcher.dispatchEvent(evt);
			}

			public synchronized void clearModel() {
				this.appointments.clear();
				this.meetings.clear();
				EventDispatcher.dispatchEvent(new AppointmentsClearedEvent(this));
				EventDispatcher.dispatchEvent(new MeetingsClearedEvent(this));
			}

			public synchronized void deleteAppointment(Employee emp, Appointment appointment) {
				List<Appointment> list = this.appointments.get(emp);
				if (list == null) {
					list = new ArrayList<Appointment>();
				}
				List<Appointment> old = new ArrayList<Appointment>(list);
				list.remove(appointment);
				AppointmentsChangedEvent evt 
				= new AppointmentsChangedEvent(this, emp, old, list);
				EventDispatcher.dispatchEvent(evt);
			}

			public synchronized void deleteMeeting(Employee employee, Meeting meeting) {
				List<Meeting> list = this.meetings.get(employee);
				if (list == null) {
					list = new ArrayList<Meeting>();
				}
				List<Meeting> old = new ArrayList<Meeting>(list);
				list.remove(meeting);
				MeetingsChangedEvent evt 
				= new MeetingsChangedEvent(this, employee, old, list);
				EventDispatcher.dispatchEvent(evt);
			}
}